package com.baidu.process.chat.core.web.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baidu.process.chat.core.web.bean.eval.AppEvalTemplate;
import com.baidu.process.chat.core.web.bean.eval.EvalResult;
import com.baidu.process.chat.core.web.bean.eval.EvalVO;
import com.baidu.process.chat.core.web.entity.EvalPushTime;
import com.baidu.process.chat.core.web.entity.Evaluation;
import com.baidu.process.chat.core.web.entity.EvaluationDTO;
import com.baidu.process.chat.core.web.mapper.EvaluationMapper;
import com.baidu.process.chat.core.web.service.IEvalPushTimeService;
import com.baidu.process.chat.core.web.service.IEvaluationService;
import com.baidu.process.constant.EvalConstant;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

/**
 * @author: lws
 * @date: 2022/11/9
 */
@Slf4j
@Service
public class EvaluationServiceImpl extends ServiceImpl<EvaluationMapper, Evaluation> implements IEvaluationService {

    /**
     * 满意度评价请求地址
     */
    @Value("${volvo.config.eval-url}")
    private String evalUrl;

    /**
     * 满意度评价页面过期时间
     */
    @Value("${volvo.config.eval-expire-time}")
    private long evalExpireTime;

    private final IEvalPushTimeService evalPushTimeService;

    public EvaluationServiceImpl(IEvalPushTimeService evalPushTimeService) {
        this.evalPushTimeService = evalPushTimeService;
    }


    @Override
    public EvalResult pushEval(EvalVO vo) {
        Assert.isTrue(StringUtils.isNotEmpty(vo.getSessionId()), "会话编码不能为空");
        if (EvalConstant.CHANNEL_APP.equals(vo.getChannel())) {
            // 记录推送时间
            savePushTime(vo.getSessionId());
            // APP渠道
            AppEvalTemplate appEvalTemplate = AppEvalTemplate.instanceOf(vo.getSessionId());
            // 设置过期时间
            appEvalTemplate.setExpireDate(((System.currentTimeMillis()+evalExpireTime))/1000);
            return EvalResult.ok(appEvalTemplate);
        } else if (EvalConstant.CHANNEL_WX.equals(vo.getChannel())) {
            // 记录推送时间
            savePushTime(vo.getSessionId());
            // 微信小程序渠道
            JSONObject result = new JSONObject();
            result.put("url", evalUrl + vo.getSessionId());
            return EvalResult.ok(result);
        } else {
            throw new RuntimeException("渠道编码错误");
        }
    }

    /**
     * 记录sessionId推送时间
     * @param sessionId
     */
    private void savePushTime(String sessionId) {
        EvalPushTime byId = evalPushTimeService.lambdaQuery()
                .eq(EvalPushTime::getSessionId, sessionId)
                .one();
        // 已经有推送数据无需再次新增
        if (Objects.isNull(byId)) {
            // 微信小程序渠道除了返回url，还需要将推送时间入库，以便判断页面时效性
            EvalPushTime evalPushTime = new EvalPushTime();
            evalPushTime.setSessionId(sessionId);
            evalPushTime.setCreateTime(System.currentTimeMillis());
            evalPushTimeService.save(evalPushTime);
        }
    }


    @Override
    public EvalResult recordEvalResult(EvalVO vo) {
        // 判断sessionId是否过期
        isExpire(vo.getSessionId());
        // 未超时才可以入库
        Evaluation evaluation = new Evaluation();
        evaluation.setSessionId(vo.getSessionId());
        evaluation.setSessionSatisfaction(vo.getSatisfied());
        evaluation.setSessionSolution(vo.getSolve());
        evaluation.setStarValue(vo.getStar_value());
        evaluation.setReason(vo.getReason());
        evaluation.setSelectItems(vo.getSelected_items());
        evaluation.setVersion(vo.getVersion());
        evaluation.setCreateDate(LocalDate.now().format(DateTimeFormatter.ISO_DATE));
        return EvalResult.ok(this.save(evaluation));
    }

    @Override
    public EvalResult getData(String sessionId) {
        Assert.isTrue(StringUtils.isNotEmpty(sessionId), "会话编码不能为空");
        // 查询满意度评价数据
        Evaluation evaluation = this.lambdaQuery()
                .eq(Evaluation::getSessionId, sessionId)
                .one();
        // 不为空返回查询到的数据
        if (!Objects.isNull(evaluation)) {
            EvaluationDTO evaluationDTO = new EvaluationDTO();
            BeanUtils.copyProperties(evaluation, evaluationDTO);
            evaluationDTO.setStarValue(StringUtils.isEmpty(evaluation.getStarValue())?0:Integer.valueOf(evaluation.getStarValue()));
            return EvalResult.ok(evaluationDTO);
        }
        // 判断sessionId是否过期
        isExpire(sessionId);
        return EvalResult.ok();
    }

    @Override
    public EvalResult del(String sessionId) {
        LambdaQueryWrapper<EvalPushTime> qw = Wrappers.lambdaQuery();
        if (StringUtils.isNotEmpty(sessionId)) {
            // sessionId 不为空的时候删除对应sessionId
            qw.eq(EvalPushTime::getSessionId, sessionId);
        } else {
            // sessionId 是空的时候删除创建时间小于过期时间之前的数据
            qw.lt(EvalPushTime::getCreateTime, System.currentTimeMillis() - evalExpireTime);
        }
        return EvalResult.ok(evalPushTimeService.remove(qw));
    }

    /**
     * 判断sessionId是否过期
     *
     * @param sessionId
     */
    private void isExpire(String sessionId) {
        // 查询页面推送时间
        EvalPushTime evalPushTime = evalPushTimeService.lambdaQuery()
                .eq(EvalPushTime::getSessionId, sessionId)
                .one();
        // 1.查不到数据，就是数据被删除了，证明页面已经失效
        // 2.有数据，则判断创建时间是否小于72小时前，是的话也返回页面已经失效
        long threeDayBefore = System.currentTimeMillis() - evalExpireTime;
        Assert.isTrue(!Objects.isNull(evalPushTime) && evalPushTime.getCreateTime() > threeDayBefore, "页面已失效");
    }
}
